package animation;

import com.crunch.graphics.gpu.GpuDrawCall;
import com.crunch.graphics.gpu.GpuProgram;
import com.crunch.graphics.gpu.GpuState;
import com.crunch.math.Matrix44f;
import com.crunch.math.Vector4f;

import javax.media.opengl.GL;
import javax.media.opengl.GL3;

/**
 * Renders skeleton for debugging.
 */
public class SkeletonRenderer {
	public SkeletonRenderer(GpuProgram program) {
		this.program = program;

		mvpMatrixIndex = program.getUniformIndex("mvpMatrix");
		lengthIndex = program.getUniformIndex("length");
		thicknessIndex = program.getUniformIndex("thickness");
		colorIndex = program.getUniformIndex("color");
	}

	public void drawSkeleton(GpuState gpuState, Matrix44f viewProjectionMatrix, Character.State state, Vector4f[] boneColors) {
		if (state.getCharacter().getSkeleton().getBoneCount() != boneColors.length) {
			throw new IllegalArgumentException("Bone color count mismatch");
		}

		// attribute-less rendering
		gpuState.unbindBuffer(GL.GL_ARRAY_BUFFER);
		program.bind();

		for (int i = 0; i < state.getCharacter().getSkeleton().getBoneCount(); ++i) {
			int index = state.getCharacter().getSkeleton().getDrawingOrderedBone(i);
			Skeleton.Bone bone = state.getCharacter().getSkeleton().getBone(index);

			Matrix44f mvpMatrix = viewProjectionMatrix.multiply(state.getBoneMatrices()[index].getGraphicsMatrix());

			program.setUniform(mvpMatrixIndex, GL3.GL_FLOAT_MAT4, mvpMatrix.getArray());
			program.setUniform(lengthIndex, GL.GL_FLOAT, new float[] { bone.getLength() });
			program.setUniform(thicknessIndex, GL.GL_FLOAT, new float[] { bone.getThickness() });
			program.setUniform(colorIndex, GL3.GL_FLOAT_VEC4, boneColors[index].getArray());

			GpuDrawCall.DrawCall dc = gpuState.createDrawCall();
			dc.setParameters(GL.GL_POINTS, 0, 1);
			dc.draw();
		}
	}

	public GpuProgram program;
	private int mvpMatrixIndex;
	private int lengthIndex;
	private int thicknessIndex;
	private int colorIndex;
}
